 /*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  * Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
  * font should be activated and used by other components.
  *******************************************************************************/

 package org.eclipse.ui.dialogs;

 import org.eclipse.core.filesystem.IFileStore;
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IPathVariableManager;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.wizard.WizardPage;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ModifyEvent;
 import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.DirectoryDialog;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.ide.dialogs.PathVariableSelectionDialog;
 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
 import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
 import org.eclipse.ui.internal.ide.dialogs.IDEResourceInfoUtils;

 /**
  * Standard resource link page for a wizard that creates a file or
  * folder resource.
  * <p>
  * This class may be instantiated; it is not intended to be subclassed.
  * </p>
  * @since 2.1
  */
 public class WizardNewLinkPage extends WizardPage {
     private String initialLinkTarget;

     private int type;

     private boolean createLink = false;

     private IContainer container;

     // widgets
 private Text linkTargetField;

     private Button browseButton;

     private Button variablesButton;

     /**
      * Creates a new resource link wizard page.
      *
      * @param pageName the name of the page
      * @param type specifies the type of resource to link to.
      * <code>IResource.FILE</code> or <code>IResource.FOLDER</code>
      */
     public WizardNewLinkPage(String pageName, int type) {
         super(pageName);
         this.type = type;
         setPageComplete(true);
     }

     /* (non-Javadoc)
      * Method declared on IDialogPage.
      */
     public void createControl(Composite parent) {
         Font font = parent.getFont();
         initializeDialogUnits(parent);
         // top level group
 Composite topLevel = new Composite(parent, SWT.NONE);
         GridLayout layout = new GridLayout();
         layout.numColumns = 3;
         topLevel.setLayout(layout);
         topLevel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
                 | GridData.HORIZONTAL_ALIGN_FILL));
         topLevel.setFont(font);
         PlatformUI.getWorkbench().getHelpSystem().setHelp(topLevel,
                 IIDEHelpContextIds.NEW_LINK_WIZARD_PAGE);

         final Button createLinkButton = new Button(topLevel, SWT.CHECK);
         if (type == IResource.FILE) {
             createLinkButton.setText(IDEWorkbenchMessages.WizardNewLinkPage_linkFileButton);
         } else {
             createLinkButton.setText(IDEWorkbenchMessages.WizardNewLinkPage_linkFolderButton);
         }
         createLinkButton.setSelection(createLink);
         GridData data = new GridData();
         data.horizontalSpan = 3;
         createLinkButton.setLayoutData(data);
         createLinkButton.setFont(font);
         SelectionListener listener = new SelectionAdapter() {
             public void widgetSelected(SelectionEvent e) {
                 createLink = createLinkButton.getSelection();
                 browseButton.setEnabled(createLink);
                 variablesButton.setEnabled(createLink);
                 linkTargetField.setEnabled(createLink);
                 setPageComplete(validatePage());
             }
         };
         createLinkButton.addSelectionListener(listener);

         createLinkLocationGroup(topLevel, createLink);
         validatePage();

         setErrorMessage(null);
         setMessage(null);
         setControl(topLevel);
     }

     /**
      * Creates the link target location widgets.
      *
      * @param locationGroup the parent composite
      * @param enabled sets the initial enabled state of the widgets
      */
     private void createLinkLocationGroup(Composite locationGroup,
             boolean enabled) {
         Font font = locationGroup.getFont();
         Label fill = new Label(locationGroup, SWT.NONE);
         GridData data = new GridData();
         Button button = new Button(locationGroup, SWT.CHECK);
         data.widthHint = button.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
         button.dispose();
         fill.setLayoutData(data);

         // link target location entry field
 linkTargetField = new Text(locationGroup, SWT.BORDER);
         data = new GridData(GridData.FILL_HORIZONTAL);
         linkTargetField.setLayoutData(data);
         linkTargetField.setFont(font);
         linkTargetField.setEnabled(enabled);
         linkTargetField.addModifyListener(new ModifyListener() {
             public void modifyText(ModifyEvent e) {
                 setPageComplete(validatePage());
             }
         });
         if (initialLinkTarget != null) {
             linkTargetField.setText(initialLinkTarget);
         }

         // browse button
 browseButton = new Button(locationGroup, SWT.PUSH);
         setButtonLayoutData(browseButton);
         browseButton.setFont(font);
         browseButton.setText(IDEWorkbenchMessages.WizardNewLinkPage_browseButton);
         browseButton.addSelectionListener(new SelectionAdapter() {
             public void widgetSelected(SelectionEvent event) {
                 handleLinkTargetBrowseButtonPressed();
             }
         });
         browseButton.setEnabled(enabled);

         fill = new Label(locationGroup, SWT.NONE);
         data = new GridData();
         data.horizontalSpan = 2;
         fill.setLayoutData(data);

         // variables button
 variablesButton = new Button(locationGroup, SWT.PUSH);
         setButtonLayoutData(variablesButton);
         variablesButton.setFont(font);
         variablesButton.setText(IDEWorkbenchMessages.WizardNewLinkPage_variablesButton);
         variablesButton.addSelectionListener(new SelectionAdapter() {
             public void widgetSelected(SelectionEvent event) {
                 handleVariablesButtonPressed();
             }
         });
         variablesButton.setEnabled(enabled);
     }

     /**
      * Returns the link target location entered by the user.
      *
      * @return the link target location entered by the user. null if the user
      * choose not to create a link.
      */
     public String getLinkTarget() {
         if (createLink && linkTargetField != null
                 && linkTargetField.isDisposed() == false) {
             return linkTargetField.getText();
         }
         return null;
     }

     /**
      * Opens a file or directory browser depending on the link type.
      */
     private void handleLinkTargetBrowseButtonPressed() {
         String linkTargetName = linkTargetField.getText();
          String selection = null;
          IFileStore store = null;
         if (linkTargetName.length() > 0) {
             store = IDEResourceInfoUtils.getFileStore(linkTargetName);
             if (store == null || !store.fetchInfo().exists()) {
                 store = null;
             }
         }
         if (type == IResource.FILE) {
             FileDialog dialog = new FileDialog(getShell());
             if (store != null) {
                 if (store.fetchInfo().isDirectory()) {
                     dialog.setFilterPath(linkTargetName);
                 } else {
                     dialog.setFileName(linkTargetName);
                 }
             }
             selection = dialog.open();
         } else {
             DirectoryDialog dialog = new DirectoryDialog(getShell());
             if (store != null) {
                 if (!store.fetchInfo().isDirectory()) {
                     linkTargetName = store.getParent().getName();
                 }
                 if (linkTargetName != null) {
                     dialog.setFilterPath(linkTargetName);
                 }
             }
             dialog.setMessage(IDEWorkbenchMessages.WizardNewLinkPage_targetSelectionLabel);
             selection = dialog.open();
         }
         if (selection != null) {
             linkTargetField.setText(selection);
         }
     }

     /**
      * Opens a path variable selection dialog
      */
     private void handleVariablesButtonPressed() {
         PathVariableSelectionDialog dialog = new PathVariableSelectionDialog(
                 getShell(), type);

         if (dialog.open() == IDialogConstants.OK_ID) {
             String [] variableNames = (String []) dialog.getResult();

             if (variableNames != null) {
                 IPathVariableManager pathVariableManager = ResourcesPlugin
                         .getWorkspace().getPathVariableManager();
                 IPath path = pathVariableManager.getValue(variableNames[0]);

                 if (path != null) {
                     linkTargetField.setText(path.toOSString());
                 }
             }
         }
     }

     /**
      * Sets the container to use for link validation.
      * This should be the parent of the new resource that is being
      * linked.
      *
      * @param container the container to use for link validation.
      */
     public void setContainer(IContainer container) {
         this.container = container;
     }

     /**
      * Sets the value of the link target field
      *
      * @param target the value of the link target field
      */
     public void setLinkTarget(String target) {
         initialLinkTarget = target;
         if (linkTargetField != null && linkTargetField.isDisposed() == false) {
             linkTargetField.setText(target);
         }
     }

     /**
      * Validates the type of the given file against the link type specified
      * during page creation.
      *
      * @param linkTargetStore file to validate
      * @return boolean <code>true</code> if the link target type is valid
      * and <code>false</code> otherwise.
      */
     private boolean validateFileType(IFileStore linkTargetStore) {
         boolean valid = true;

         if (type == IResource.FILE && linkTargetStore.fetchInfo().isDirectory()) {
             setErrorMessage(IDEWorkbenchMessages.WizardNewLinkPage_linkTargetNotFile);
             valid = false;
         } else if (type == IResource.FOLDER
                 && !linkTargetStore.fetchInfo().isDirectory()) {
             setErrorMessage(IDEWorkbenchMessages.WizardNewLinkPage_linkTargetNotFolder);
             valid = false;
         }
         return valid;
     }

     /**
      * Validates the name of the link target
      *
      * @param linkTargetName link target name to validate
      * @return boolean <code>true</code> if the link target name is valid
      * and <code>false</code> otherwise.
      */
     private boolean validateLinkTargetName(String linkTargetName) {
         boolean valid = true;

         if ("".equals(linkTargetName)) {//$NON-NLS-1$
 setErrorMessage(IDEWorkbenchMessages.WizardNewLinkPage_linkTargetEmpty);
             valid = false;
         } else {
             IPath path = new Path("");//$NON-NLS-1$
 if (path.isValidPath(linkTargetName) == false) {
                 setErrorMessage(IDEWorkbenchMessages.WizardNewLinkPage_linkTargetInvalid);
                 valid = false;
             }
         }
         return valid;
     }

     /**
      * Returns whether this page's controls currently all contain valid
      * values.
      *
      * @return <code>true</code> if all controls are valid, and
      * <code>false</code> if at least one is invalid
      */
     private boolean validatePage() {
         boolean valid = true;
         IWorkspace workspace = IDEWorkbenchPlugin.getPluginWorkspace();

         if (createLink) {
             String linkTargetName = linkTargetField.getText();

             valid = validateLinkTargetName(linkTargetName);
             if (valid) {
                 IFileStore linkTargetFile = IDEResourceInfoUtils.getFileStore(linkTargetName);
                 if (linkTargetFile == null || !linkTargetFile.fetchInfo().exists()) {
                     setErrorMessage(IDEWorkbenchMessages.WizardNewLinkPage_linkTargetNonExistent);
                     valid = false;
                 } else {
                     IStatus locationStatus = workspace.validateLinkLocation(
                             container, new Path(linkTargetName));

                     if (locationStatus.isOK() == false) {
                         setErrorMessage(IDEWorkbenchMessages.WizardNewLinkPage_linkTargetLocationInvalid);
                         valid = false;
                     } else {
                         valid = validateFileType(linkTargetFile);
                     }
                 }
             }
         }
         // Avoid draw flicker by clearing error message
 // if all is valid.
 if (valid) {
             setMessage(null);
             setErrorMessage(null);
         }
         return valid;
     }
 }

